package com.mayflygeek.mayflyask.framework.webmvc.controller;

import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.ui.ModelMap;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.mayflygeek.mayflyask.framework.core.Idable;
import com.mayflygeek.mayflyask.framework.webmvc.event.Events;
import com.mayflygeek.mayflyask.framework.webmvc.message.Message;
import com.mayflygeek.mayflyask.framework.webmvc.message.MessageBuilder;

/**
 * 
 * @author 虫虫
 * @team 蜉蝣极客
 * @link www.mayflygeek.com
 * @Emial chongchong@mayflygeek.com
 *
 */
public abstract class JqueryGridCrudController<T extends Idable<Long>> extends CrudController<T> {
	private Logger logger = LoggerFactory.getLogger(JqueryGridCrudController.class);

	@RequestMapping(method = GET)
	public String index(ModelMap model) {
		return view("index");
	}

	@SuppressWarnings("unchecked")
	@RequestMapping("/list")
	@ResponseBody
	public Page<T> listData(HttpServletRequest request) {
		return (Page<T>) list(request);
	}

	@RequestMapping(params = "oper=add", method = POST)
	@ResponseBody
	public Message create(@Valid T entity, BindingResult bindingResult) {
		if (bindingResult.hasErrors()) {
			return MessageBuilder.error("输入有误！").detail(getBindingErrorsString(bindingResult)).build();
		}

		try {
			beforeCreate(entity);
			doCreate(entity);

			try {
				publishEvent(Events.afterCreateEvent(entity));
			} catch (Exception e) {
				logger.warn("执行afterCreate出错", e);
			}
			return MessageBuilder.success("保存成功！").build();
		} catch (Exception e) {
			return logExceptionMessage(e, "保存失败！");
		}
	}

	@RequestMapping(value = { "/{id}/edit" }, method = GET)
	@ResponseBody
	public T edit(@PathVariable("id") Long id, ModelMap model) {
		return getBaseDao().find(id);
	}

	@RequestMapping(value = { "/{id}" }, method = GET)
	@ResponseBody
	public T show(@PathVariable("id") Long id, ModelMap model) {
		return getBaseDao().find(id);
	}

	@RequestMapping(params = "oper=edit", method = POST)
	@ResponseBody
	public Message update(@RequestParam(value = "id", required = true) Long id) {
		try {
			final T entity = getBaseDao().get(id);
			BindingResult bindingResult = this.bind(entity); // 将request
			// 请求参数转换为 Javabean.
			if (bindingResult.hasErrors()) {
				return MessageBuilder.error("输入有误!").detail(getBindingErrorsString(bindingResult)).build();
			}
			beforeUpdate(entity);
			doUpdate(entity);

			try {
				publishEvent(Events.afterUpdateEvent(entity));
			} catch (Exception e) {
				logger.warn("执行afterCreate出错", e);
			}

			return MessageBuilder.success("操作成功!").build();
		} catch (Exception e) {
			return logExceptionMessage(e, "更新失败");
		}
	}

	@RequestMapping(params = "oper=del", method = POST)
	@ResponseBody
	public Message delete(@RequestParam(value = "id", required = true) Long id) {
		try {
			T entity = getBaseDao().find(id);
			Assert.notNull(entity, "对象不存在!");

			beforeDelete(entity);
			doDelete(entity);

			try {
				publishEvent(Events.afterDeleteEvent(entity));
			} catch (Exception e) {
				logger.warn("执行afterDelete出错", e);
			}

			return MessageBuilder.success("操作成功!").build();
		} catch (Exception e) {
			return logExceptionMessage(e, "删除失败");
		}
	}

	protected void beforeCreate(T entity) throws Exception {
		//
	}

	protected void beforeUpdate(T entity) throws Exception {
		//
	}

	protected void beforeDelete(T entity) throws Exception {
		//
	}
}